<template>
  <div class="w-table" v-loading="loading" element-loading-text="正在加载中"
       :class="{'w-table_moving': dragState.dragging, 'w-table-no-header-input': option.hideInput, [option.tableClassName]: true, 'w-table-no-operation': option.noOperation || isHiddenOperation}">
    <div class="w-table-operation clearfix" v-if="hasOperationBtn">
      <!-- <el-tooltip class="item" effect="dark" content="展开操作栏" placement="left-start">
        <el-button size="hn-icon-small" class="fl" v-if="isHiddenOperation" @click="onToggleOperation">
          <i class="el-icon-plus"></i>
        </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="收起操作栏" placement="left-start">
        <el-button size="hn-icon-small" class="fl" v-if="!isHiddenOperation" title="收起操作栏" @click="onToggleOperation">
          <i class="el-icon-minus"></i>
        </el-button>
      </el-tooltip> -->
    </div>
    <el-table ref="table" :row-key="rowKey" @row-dblclick="rowDblclick" id="applyTable"
              v-if="tableHeader && tableHeader.length || option.custom" fit highlight-current-row stripe
              :row-class-name="rowClassName"
              :header-row-class-name="option.tableHeader?'common-table-header common-table-header-' + option.tableHeader:'common-table-header'"
              class="common-table" :data="data" :border="option.border" :default-expand-all="option.defaultExpandAll"
              :height="option.height" :max-height="option.maxHeight" :min-height="option.minHeight"
              :style="{ width: parseInt(option.width)+'px' }" :header-cell-class-name="headerCellClassName"
              @selection-change="selectionChange" @select="checkRowCheckboxChange" @select-all="selectAll"
              @header-dragend="colChange" >>
      <el-table-column
        type="selection" align="center"
        width="55" class-name="col-index" :selectable='option.selectable' v-if="option.hasSelection">
      </el-table-column>
      <template v-for="(col, index) in tableHeader">
        <template v-if="handleColumn(col)"></template>
        <el-table-column :show-overflow-tooltip="true" v-else-if="col.type === 'index'"
                         type="index" :sortable="col.sortable" align="center"
                         :width="col.width" class-name="col-index" :index="col.indexMethod || indexMethod"
                         :label="col.label" :key="index">
        </el-table-column>
        <el-table-column :sortable="col.sortable" :show-overflow-tooltip="true" v-else-if="col.isHidden"
                         :class-name="col.className" :filters="col.filters" :filter-method="col.filterMethod"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop"
                         :label="col.label" :width="col.width" :min-width="col.minWidth" :type="col.type"
                         :header-align="col.headerAlign" :column-key="index.toString()" :render-header="renderHeader">
          <template slot-scope="scope">
            <span></span>
          </template>
        </el-table-column>
        <el-table-column :sortable="col.sortable" :show-overflow-tooltip="true" v-else-if="col.onClick"
                         :class-name="col.className" :filters="col.filters" :filter-method="col.filterMethod"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop"
                         :label="col.label" :width="col.width" :min-width="col.minWidth" :type="col.type"
                         :header-align="col.headerAlign" :column-key="index.toString()" :render-header="renderHeader">
          <template slot-scope="scope">
            <a class="common-link" v-if="!handleHidden(col, scope)" @click="col.onClick(scope.row)">{{scope.row[col.prop]}}</a>
          </template>
        </el-table-column>
        <el-table-column :sortable="col.sortable" v-else-if="col.isImg" :class-name="col.className"
                         :filters="col.filters" :filter-method="col.filterMethod"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop" :label="col.label"
                         :width="col.width" :min-width="col.minWidth" :type="col.type" :header-align="col.headerAlign"
                         :column-key="index.toString()" :render-header="renderHeader">
          <template slot-scope="scope">
            <el-popover
              placement="right-start"
              popper-class="table-img-popper"
              title=""
              :open-delay="1000"
              trigger="hover">
              <img class="common-img" slot="reference"
                   :src="scope.row[col.prop]?imgServerUrl + scope.row[col.prop]:''"/>
              <!-- <img class="common-img-hover" onerror="this.src='../../assets/image/default.png'"
                   :src="scope.row[col.prop]?imgServerUrl + scope.row[col.prop]:''"/> -->
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column :sortable="col.sortable" v-else-if="col.type === 'expand'" :class-name="col.className"
                         :filters="col.filters" :filter-method="col.filterMethod"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop" :label="col.label"
                         :width="col.width" :min-width="col.minWidth" type="expand" :header-align="col.headerAlign"
                         :column-key="index.toString()" :render-header="renderHeader">
          <template slot-scope="scope">
            <el-table :data="scope.row.productsList" class="product-table" fit stripe v-if="prodctHeader && prodctHeader.length">
                <template v-for="(productCol, productIndex) in prodctHeader">
                  <el-table-column  :prop="productCol.prop" :label="productCol.label" align="center" width="180" :key="productIndex"></el-table-column>
                </template>
            </el-table>
          </template>
        </el-table-column>
        <el-table-column :sortable="col.sortable" :show-overflow-tooltip="true" v-else-if="col.render"
                         :class-name="col.className" :filters="col.filters" :filter-method="col.filterMethod"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop" :align="col.align || option.align"
                         :label="col.label" :width="col.width" :min-width="col.minWidth" :fixed="handleFixed(col)" :type="col.type"
                         :header-align="col.headerAlign" :column-key="index.toString()" :render-header="renderHeader">
          <template slot-scope="scope">
            <table-column-custom
              :render="col.render"
              :row="scope.row"
              :index="index"
              :column="col"
            >
            </table-column-custom>
          </template>
        </el-table-column>
        <el-table-column :sortable="col.sortable" :show-overflow-tooltip="true" v-else :class-name="col.className"
                         :filters="col.filters" :filter-method="col.filterMethod" :align="col.align || option.align"
                         :filter-placement="col.filterPlacement" :key="index" :prop="col.prop" :label="col.label"
                         :width="col.width" :min-width="col.minWidth" :type="col.type" :header-align="col.headerAlign"
                         :column-key="index.toString()" :render-header="renderHeader">
        </el-table-column>
      </template>
      <slot></slot>
      <slot name="fixed" v-if="!isHiddenOperation"></slot>
      <slot name="empty" slot="empty"></slot>
    </el-table>
    <div class="" v-if="data && !data.length">
      <slot name="table-empty"></slot>
    </div>
  </div>
</template>

<script>
  import { mapGetters } from 'vuex'
  import tableColumnCustom from '@/components/TableColumnCustom/index'

  export default {
    name: 'draggable-table',
    components: {
      tableColumnCustom
    },
    props: {
      hasOperationBtn: {
        default: true,
        type: Boolean
      },
      // 当前页
      orderMenu: {
        default: '',
        type: String
      },
      // 当前页
      currentPage: {
        default: 1,
        type: Number
      },
      // 每页项数
      pageSize: {
        default: 20,
        type: Number
      },
      // 序号字段
      rowKey: {
        default: '',
        type: String
      },
      // 是否加载中
      loading: {
        default: true,
        type: Boolean
      },
      // 数据绑定
      data: {
        default: function() {
          return []
        },
        type: Array
      },
      // 表头数据
      header: {
        default: function() {
          return []
        },
        type: Array
      },
      proHeader: {
        default: function() {
          return []
        },
        type: Array
      },
      /**
       * {
       *    noOperation: 是否没有操作功能，处理行高兼容
       *    hideInput: 是否隐藏表头的输入框
       *    border: 是否有边框,
       *    minHeight: 最小高度,
       *    rowDblclick: 鼠标双击事件,
       *    search: 输入框搜索,
       *    submit: 提交事件
       * }
       **/
      option: {
        default: function() {
          return {}
        },
        type: Object
      }
    },
    data() {
      return {
        imgServerUrl: '',
        tableHeader: this.header,
        prodctHeader: this.proHeader,
        isHiddenOperation: this.option.noOperation || false,
        dragState: {
          start: -1, // 起始元素的 index
          end: -1, // 结束元素的 index
          move: -1, // 移动鼠标时所覆盖的元素 index
          dragging: false, // 是否正在拖动
          direction: undefined // 拖动方向
        }
      }
    },
    computed: {
      // ...mapGetters([
      //   'imgServerUrl'
      // ])
    },
    watch: {
      header(val, oldVal) {
        this.tableHeader = val
      },
      proHeader(val, oldVal) {
        this.prodctHeader = val
      }
    },
    created() {
      // 蓝色表头的表格里的内容都居中展示（未定义居中属性）
      if (this.option.tableHeader === 'lightblue' || this.option.tableHeader === 'light') {
        this.tableHeader.forEach(item => {
          if (typeof item.align === 'undefined') {
            item.align = 'center'
          }
        })
      }
    },
    methods: {
      /**
       * 处理fixed
       */
      handleFixed(col) {
        if (typeof col.fixed === 'function') {
          return col.fixed()
        } else {
          return col.fixed
        }
      },
      /**
       * 处理隐藏
       */
      handleHidden(col, scope) {
        if (typeof col.hiddenClick === 'function') {
          return col.hiddenClick(scope)
        } else {
          return col.hiddenClick
        }
      },
      /**
       * 处理是否隐藏列
       */
      handleColumn(col) {
        if (typeof col.isHiddenAll === 'function') {
          return col.isHiddenAll()
        } else {
          return col.isHiddenAll
        }
      },
      /**
       * 响应操作栏显隐
       */
      onToggleOperation() {
        this.isHiddenOperation = !this.isHiddenOperation
        this.$emit('update:isHiddenOperation', this.isHiddenOperation)
      },
      /**
       * 拖动表头改变列宽
       */
      colChange(newWidth, oldWidth, column, event) {
        var self = this
        setTimeout(() => {
          console.log(newWidth, oldWidth, column, event)
          console.log('拖动表头改变列宽')
          // var applyTable = document.getElementById('applyTable')
          // var applyTableColgroup = applyTable.getElementsByTagName('colgroup')[0]
          // var applyTableCol = applyTableColgroup.getElementsByTagName('col')
          // console.log('applyTableCol=', applyTableCol)
          // for (var i = 0; i < self.tableHeader.length; i++) {
          //     self.tableHeader[i].width = newWidth
          // }
          self.tableHeader[column.columnKey].width = newWidth
          console.log(self.tableHeader)
        }, 100)
      },
      /**
       * 设置操作栏显隐
       */
      setOperation(isHiddenOperation) {
        this.isHiddenOperation = isHiddenOperation
        this.$emit('update:isHiddenOperation', this.isHiddenOperation)
      },
      /**
       * 重置输入框、排序、筛选
       */
      onReset() {
        this.$refs['table'].clearSort()
        this.$refs['table'].clearFilter()
        this.clearInput()
      },
      /**
       * 序号方法
       * @param index 索引
       * @returns {*}
       */
      indexMethod(index) {
        return index + (this.currentPage - 1) * this.pageSize + 1
      },
      /**
       * 行双击方法
       * @param row
       * @param event
       */
      rowDblclick(row, event) {
        if (this.option && this.option.rowDblclick) {
          this.option.rowDblclick(row, event)
        }
      },
      /**
       * 行选择方法
       * @param val 行数据
       */
      selectionChange(val) {
        if (this.option && this.option.handleSelectionChange) {
          this.option.handleSelectionChange(val)
        }
      },
      checkRowCheckboxChange(val, row) {
        if (this.option && this.option.handleSelectionBoxChange) {
          this.option.handleSelectionBoxChange(val, row)
        }
      },
      selectAll(val) {
        if (this.option && this.option.handleSelectAll) {
          this.option.handleSelectAll(val)
        }
      },
      /**
       * 清空输入框内容
       */
      clearInput() {
        const headerInputs = document.getElementsByClassName('header-input')
        for (const item of headerInputs) {
          item.value = ''
        }
      },
      /**
       * 处理表头的数据
       * @param createElement
       * @param column
       * @param $index
       * @returns {*}
       */
      renderHeader(createElement, {
        column,
        $index
      }) {
        let el = null
        if (this.tableHeader && this.tableHeader[column.columnKey] && !this.tableHeader[column.columnKey].hideInput && !this.option.hideInput) {
          el = createElement('span', {
            style: {
              position: 'absolute',
              left: '10px',
              right: '10px',
              top: '0',
              zIndex: 2
            }
          }, [
            this.tableHeader && this.tableHeader[column.columnKey] && this.tableHeader[column.columnKey].renderHeader ? this.tableHeader[column.columnKey].renderHeader(createElement) : createElement('input', {
              style: {
                width: '100%',
                borderRadius: '5px',
                marginBottom: '10px',
                marginTop: '8px',
                height: '24px',
                outline: 'none',
                padding: '0 10px',
                fontSize: '13px',
                border: '1px solid #f0f0f0'
              },
              on: {
                keyup: ($event) => {
                  $event.stopPropagation()
                  if ($event.keyCode === 13) {
                    if (this.tableHeader[column.columnKey].search) {
                      this.tableHeader[column.columnKey].submit($event.target.value, this.tableHeader[column.columnKey].key || this.tableHeader[column.columnKey].prop || '')
                    } else {
                      this.option.submit($event.target.value, this.tableHeader[column.columnKey].key || this.tableHeader[column.columnKey].prop || '')
                    }
                  }
                },
                input: ($event) => {
                  $event.stopPropagation()
                  if (this.tableHeader[column.columnKey].search) {
                    this.tableHeader[column.columnKey].search($event.target.value, this.tableHeader[column.columnKey].key || this.tableHeader[column.columnKey].prop || '')
                  } else {
                    this.option.search($event.target.value, this.tableHeader[column.columnKey].key || this.tableHeader[column.columnKey].prop || '')
                  }
                },
                click: ($event) => {
                  $event.stopPropagation()
                }
              },
              attrs: {
                'disabled': this.tableHeader && this.tableHeader[column.columnKey] && this.tableHeader[column.columnKey].disabled || false,
                'class': 'header-input',
                'type': 'text'
              }
            })
          ])
        }
        return createElement(
          'div', {
            'class': ['thead-cell'],
            on: {
              mousedown: ($event) => {
                this.handleMouseDown($event, column)
              },
              mouseup: ($event) => {
                this.handleMouseUp($event, column)
              },
              mousemove: ($event) => {
                this.handleMouseMove($event, column)
              }
            }
          }, [
            createElement('span', {
              'class': ['virtual']
            }),
            el,
            createElement('a', column.label)
          ])
      },
      /**
       * 按下鼠标开始拖动
       * @param e
       * @param column
       */
      handleMouseDown(e, column) {
        this.dragState.dragging = true
        this.dragState.start = parseInt(column.columnKey)
        // 给拖动时的虚拟容器添加宽高
        const table = document.getElementsByClassName('w-table')[0]
        const virtual = document.getElementsByClassName('virtual')
        for (const item of virtual) {
          item.style.height = table.clientHeight - 1 + 'px'
          item.style.width = item.parentElement.parentElement.clientWidth + 'px'
        }
      },
      /**
       * 鼠标放开结束拖动
       * @param e
       * @param column
       */
      handleMouseUp(e, column) {
        this.dragState.end = parseInt(column.columnKey) // 记录起始列
        if (this.dragState.start !== this.dragState.end) {
          this.dragColumn(this.dragState)
        }
        // 初始化拖动状态
        this.dragState = {
          start: -1,
          end: -1,
          move: -1,
          dragging: false,
          direction: undefined
        }
        // 给拖动时的虚拟容器添加宽高
        const virtual = document.getElementsByClassName('virtual')
        for (const item of virtual) {
          item.style.height = '0px'
          item.style.width = '0px'
        }
      },
      /**
       * 拖动中
       * @param e
       * @param column
       * @returns {boolean}
       */
      handleMouseMove(e, column) {
        if (this.dragState.dragging) {
          const index = parseInt(column.columnKey) // 记录起始列
          if (index - this.dragState.start !== 0) {
            this.dragState.direction = index - this.dragState.start < 0 ? 'left' : 'right' // 判断拖动方向
            if (this.option && this.option.hasSelection) {
              this.dragState.move = parseInt(column.columnKey) + 1
            } else {
              this.dragState.move = parseInt(column.columnKey)
            }
          } else {
            this.dragState.direction = undefined
          }
        } else {
          return false
        }
      },
      /**
       * 拖动易位
       * @param start
       * @param end
       * @param direction
       */
      dragColumn({
        start,
        end,
        direction
      }) {
        const tempData = []
        const left = direction === 'left'
        const min = left ? end : start - 1
        const max = left ? start + 1 : end
        if (start < 0 || max < 0) {
          return
        }
        for (let i = 0; i < this.tableHeader.length; i++) {
          if (i === end) {
            tempData.push(this.tableHeader[start])
          } else if (i > min && i < max) {
            tempData.push(this.tableHeader[left ? i - 1 : i + 1])
          } else {
            tempData.push(this.tableHeader[i])
          }
        }
        this.tableHeader = []
        this.$nextTick(() => {
          this.tableHeader = tempData
        })
      },
      /**
       * 表头class
       * @param column
       * @param columnIndex
       * @returns {string}
       */
      headerCellClassName({
        column,
        columnIndex
      }) {
        return (columnIndex === this.dragState.move ? `darg_active_${this.dragState.direction}` : '')
      },
      rowClassName({ row, rowIndex }) {
        row.eltTableIndex = rowIndex
      }
    }
  }
</script>

<style rel="stylesheet/scss" lang="scss">
  @import "~@/assets/styles/variables.scss";

  .w-table .thead-cell{
    color: #515a6e !important;
  }

  .table-img-popper {
    padding: 10px;
    .common-img-hover {
      display: block;
      width: 260px;
      height: 260px;
    }
  }

  .w-table {
    position: relative;
    z-index: 1;
    font-size: $baseFs;
    button[disabled] {
      color: #999 !important;
    }
    .w-table-operation {
      position: absolute;
      right: -23px;
      width: 20px;
      top: 0;
    }
    &.w-table-no-operation td {
      height: 36px !important;
    }
    .hn-fc-blue {
      color: #3578ba;
      a {
        color: #fff;
        &.common-link {
          color: #3578ba;
        }
      }
    }
    .common-link:hover {
      text-decoration: underline;
    }
    .common-img {
      display: block;
      width: 30px;
      height: 30px;
      margin: 5px auto;
    }
    td.td-color-red {
      color: $red;
    }
    .common-table {
      font-size: $baseFs;
      border-radius: 4px 4px 0 0;
      overflow: hidden;
      input, select {
        font-size: 13$baseFs;
      }
      .fixed-width {
        border-radius: 0 4px 0 0;
      }
      td .cell {
        text-overflow: ellipsis;
        overflow: hidden;
        white-space: nowrap;
      }
      td, th {
        padding: 5px 0 !important;
      }
      th {
        background: transparent;
        text-align: center;
        .cell.highlight {
          color: #fff
        }
      }
      .overflow-none .cell {
        overflow: auto;
        white-space: normal;
        text-overflow: inherit;
      }
      .product-table {
        border: none !important;
        th, td {
          border: none !important;
          padding:5px !important;
        }
      }
      .product-table:before {
        height: 0;
      }
    }
    .el-table--border {
      border: 0;
      tr td {
        border-right-width: 0;
      }
    }
    th.col-index .cell {
      position: relative;
      bottom: -14px;
      color: #FFFFFF;
    }
    .el-table__column-filter-trigger {
      line-height: 23px;
    }
    .common-table-header {
      background: #5181b0;
      color: #fff;
      th {
        border-right: 1px solid #fff;
      }
      &.common-table-header-lightblue {
        background: $gray;
        th {
          border-right: 1px solid $black;
          border-bottom: 1px solid $black;
        }
      }
      &.common-table-header-light {
        background: #FAFAFA;
        color: #666;
        th {
          border-right: 1px solid #FAFAFA;
          border-bottom: 1px solid #FAFAFA;
        }
      }
    }
    .el-table {
      .el-select {
        display: block;
      }
      td {
        border-bottom-width: 0;
      }
      th {
        padding: 0;
        .virtual {
          position: absolute;
          left: 0;
          top: 0;
          display: block;
          width: 0;
          height: 0;
          z-index: 1;
          background: none;
          border: none;
        }
        > .cell {
          padding: 0;
        }
        &.darg_active_left {
          .virtual {
            border-left: 2px dotted #666;
          }
        }
        &.darg_active_right {
          .virtual {
            border-right: 2px dotted #666;
          }
        }
      }
    }
    .thead-cell {
      padding: 0;
      display: inline-flex;
      flex-direction: column;
      align-items: left;
      cursor: pointer;
      overflow: initial;
      color: #FFFFFF;
      > a {
        padding-top: 30px;
        line-height: 30px;
      }
      &:before {
        content: "";
        position: absolute;
        top: 0;
        left: 5px;
        bottom: 0;
        right: 5px;
      }
    }
    &.w-table-no-header-input {
      .thead-cell {
        padding: 0;
        > a {
          padding-top: 0;
          line-height: inherit;
        }
      }
      th {
        line-height: 36px;
      }
      th.col-index .cell {
        position: relative;
        bottom: 0;
      }
      .common-table {
        border: 1px solid $black;
        border-radius: 4px;
      }
      &.hn-light-table {
        .common-table {
          border: 1px solid #e8e8e8;
          border-radius: 4px;
        }
      }
    }
    &.w-table_moving {
      .el-table th .thead-cell {
        cursor: move !important;
      }
      .el-table__fixed {
        cursor: not-allowed;
      }
    }
    .header-input-date {
      width: 100%;
      border-radius: 5px;
      outline: none;
      padding: 0;
      font-size: $baseFs;
      input {
        height: 24px;
        line-height: 24px;
        border: 1px solid rgb(240, 240, 240);
      }
    }
    .header-input-select {
      width: 100%;
      border-radius: 5px;
      margin-top: 8px;
      height: 24px;
      outline: none;
      padding: 0;
      font-size: $baseFs;
      input {
        height: 24px;
        line-height: 24px;
        border: 1px solid rgb(240, 240, 240);
      }
      .el-input {
        height: 24px;
        line-height: 24px;
        padding: 0;
      }
      .el-input--medium .el-input__icon {
        height: 24px;
        line-height: 24px;
        background: url('../../assets/image/btn-select.png') no-repeat center;
        background-size: 65% auto;
        &:before {
          display: none;
        }
      }
    }
  }
</style>
